// Copyright (c) Huawei Technologies Co., Ltd. 2025. All rights reserved.
// This source file is part of the Cangjie project, licensed under Apache-2.0
// with Runtime Library Exception.
//
// See https://cangjie-lang.cn/pages/LICENSE for license information.

#include <memory>
#include <regex>

#include "cangjie/AST/Walker.h"

#include "Platform/TempDirectory.h"

#include "Util/Io.h"

#include "Migrators/FileMigrator.h"

using namespace CangjieMigrator;

FileMigrator::FileMigrator(Path cangjieHome, Option option,
    std::string version, std::unique_ptr<Rules::RuleList> rules)
    : Migrator(option, std::move(rules)),
    compiler(CangjieTools::Compiler(std::move(cangjieHome))),
    source(option.source), target(option.target),
    importPath(option.importPath), file(option.source)
{}

using namespace Cangjie::AST;

static void GenerateRemoveTestMacroFile(const Path& source, const Path& target)
{
    // Regex to match lines starting with "@Test" or "@TestCase", followed by a non-word character
    static auto testRegex = std::regex(R"(^\s*@Test(?:Case)?(?:$|\W))");

    auto lines = Util::Io::ReadAllLines(source);
    for (auto& line : lines) {
        if (std::regex_search(line, testRegex)) {
            line = "// " + line;
        }
    }
    Util::Io::WriteAllLines(target, lines);
}

bool FileMigrator::Convert()
{
    // 0. 使用移除了@Test和@TestCase宏的参加编译
    const auto tempDir = Platform::TempDirectory();
    const auto sourceRemove = tempDir.GenerateUniqueFilePath();
    GenerateRemoveTestMacroFile(source, sourceRemove);

    // 1. 编译源文件的语义信息
    compiler.CompileSemaFile({sourceRemove}, {importPath});

    const auto rootNode = compiler.GetAstRootNode();
    if (!rootNode) {
        std::cerr << "File migrator convert file " << file.GetPath() << " AST root node is nullptr. " << std::endl;
        return false;
    }
    CangjieTools::Compiler::TraverseAst(rootNode, rules, file);

    // 3. 修改ImportInfo
    file.ChangeImport();

    // 4. 将上一步完成的UpdateList根据修改的Position写入target
    if (!file.Generate(target)) {
        std::cerr << "File migrator convert file " << file.GetPath() << " failed when generate to " << target << ".";
        return false;
    }

    if (file.NeedImportStdx()) {
        std::cout << "Some std packages used in the file have been moved to stdx. Please download and add a reference "
                     "to stdx."
                  << std::endl;
    }

    return true;
}
